package com.fanketly.accompanist.banner

import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.hardware.SensorManager.SENSOR_DELAY_GAME
import android.util.Log
import androidx.annotation.DrawableRes
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.material.Surface
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.imageResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat
import com.fanketly.accompanist.TAG
import kotlin.math.abs
import kotlin.math.roundToInt

/**
 *自动缩放比例，适合占整个组件的图片
 **/
@Deprecated("仅做示例使用")
@Composable
fun Banner3D(
    @DrawableRes backImg: Int,
    @DrawableRes midImg: Int,
    @DrawableRes foreImg: Int,
    height: Dp,
    modifier: Modifier = Modifier,
    isHeightProportion: Boolean = true,
    mMaxAngle: Int = 30,
    maxOffset: Int = 30
) {
    val imageBack = ImageBitmap.imageResource(id = backImg)
    val imageFore = ImageBitmap.imageResource(id = foreImg)
    val density = LocalDensity.current

    var xDistance by remember { mutableStateOf(0f) }
    var yDistance by remember { mutableStateOf(0f) }
    val context = LocalContext.current
    val sensorManager: SensorManager? =
        ContextCompat.getSystemService(context, SensorManager::class.java)
    val sensor = sensorManager?.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
    //时间
    val dT = SENSOR_DELAY_GAME
    var angleX = 0f
    var angleY = 0f
//    var angularZ = 0f
    var x: Float
    var y: Float
    var z: Float
    sensorManager?.registerListener(object : SensorEventListener {
        override fun onSensorChanged(event: SensorEvent?) {
            //X轴角速度 event.values?.get(0)!!
            // 将手机在各个轴上的旋转角度相加
            event?.run {
                //角速度乘以时间，就是转过的角度，直接计算旋转的角度值。
                angleX += (values[0] * dT).toLong()
                angleY += (values[1] * dT).toLong()
//                angularZ += (values[2] * dT).toLong()
                //设置x轴y轴最大边界值，
                if (angleY > mMaxAngle) {
                    angleY = mMaxAngle.toFloat()
                } else if (angleY < -mMaxAngle) {
                    angleY = -mMaxAngle.toFloat()
                }

                if (angleX > mMaxAngle) {
                    angleX = mMaxAngle.toFloat()
                } else if (angleX < -mMaxAngle) {
                    angleX = -mMaxAngle.toFloat()
                }
                //依据公式:旋转角度/最大角度 = 平移距离/最大平移距离,反推出 平移距离= 旋转角度/最大角度*最大平移距离
                val xRadio: Float = (angleY / mMaxAngle)
                val yRadio: Float = (angleX / mMaxAngle)
                x = abs(values[0])
                y = abs(values[1])
                z = abs(values[2])
//                Log.i(TAG, "onSensorChanged: $x,$y,$z")
                if (x > y + z) {
//                    xDistance = 0f
                    yDistance = yRadio * maxOffset
                } else if (y > x + z) {
                    xDistance = xRadio * maxOffset
//                    yDistance = 0f
                }

            }
        }

        override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
        }
    }, sensor, dT)

    Surface {
        val view = LocalView.current

        val foreHeight = imageFore.height
        val foreWidth = imageFore.width
        val foreHeightProportion: Int
        val foreWidthProportion: Int

        val backHeight = imageBack.height
        val backWidth = imageBack.width
        val backHeightProportion: Int
        val backWidthProportion: Int

        val h: Int
        with(density) {
            h = height.roundToPx()
        }
        //计算比例
        if (isHeightProportion) {
            val d = foreHeight.toDouble() / h
            foreHeightProportion = foreHeight / d.roundToInt()
            foreWidthProportion = foreWidth / d.roundToInt()

            val d2 = backHeight.toDouble() / h
            backHeightProportion = backHeight / d2.roundToInt()
            backWidthProportion = backWidth / d2.roundToInt()
        } else {
            val d = foreWidth.toDouble() / view.width
            foreHeightProportion = foreHeight / d.roundToInt()
            foreWidthProportion = foreWidth / d.roundToInt()

            val d2 = backWidth.toDouble() / view.width
            backHeightProportion = backHeight / d2.roundToInt()
            backWidthProportion = backWidth / d2.roundToInt()
        }

        Log.i(TAG, "Banner3D:w:${view.width} h:${view.height} ")
        Log.i(TAG, "Back:h:$backHeight,w:$backWidth h:$backHeightProportion,w:$backWidthProportion")
        Log.i(
            TAG, "Fore:h:$foreHeight,w:$foreWidth h:$foreHeightProportion,w:$foreWidthProportion"
        )

        Image(painter = painterResource(id = midImg),
            contentScale = ContentScale.Inside,
            contentDescription = null,
            modifier = modifier
                .fillMaxWidth()
                .height(height)
                .scale(1.3f)
                .drawWithContent {
                    Log.i(TAG, "Banner3D:Image")
                    translate(-xDistance, -yDistance) {
                        drawImage(
                            imageBack,
                            dstSize = IntSize(backWidthProportion, backHeightProportion),
                        )
                    }
                    drawContent()
                    translate(xDistance, yDistance) {
                        drawImage(
                            imageFore,
                            dstSize = IntSize(foreWidthProportion, foreHeightProportion),
                        )
                    }
                })
    }
}

/***
 * @param midImg  图片Id
 * @param height Banner图片高度
 * @param modifier 图片的修饰符
 * @param contentScale 图片缩放方式
 * @param mMaxAngle 最大角度
 * @param maxOffset 最大位移
 * @param onDraw 在此绘制
 * Example: translate(-xDistance, -yDistance) {
 *      drawImage(
 *          imageBack,
 *          dstSize = IntSize(backWidthProportion, backHeightProportion),
 *      )
 *  }
 *  drawContent()
 *  translate(xDistance, yDistance) {
 *      drawImage(
 *          imageFore,
 *          dstSize = IntSize(foreWidthProportion, foreHeightProportion),
 *      )
 *  }
 */
@Composable
fun Banner3D(
    @DrawableRes midImg: Int,
    height: Dp,
    modifier: Modifier = Modifier,
    contentScale: ContentScale = ContentScale.Inside,
    mMaxAngle: Int = 30,
    maxOffset: Int = 30,
    onDraw: ContentDrawScope.(xDistance: Float, yDistance: Float) -> Unit
) {
    var xDistance by remember { mutableStateOf(0f) }
    var yDistance by remember { mutableStateOf(0f) }
    val context = LocalContext.current
    val sensorManager: SensorManager? =
        ContextCompat.getSystemService(context, SensorManager::class.java)
    val sensor = sensorManager?.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
    //时间
    val dT = SENSOR_DELAY_GAME
    var angleX = 0f
    var angleY = 0f
    var x: Float
    var y: Float
    var z: Float
    sensorManager?.registerListener(object : SensorEventListener {
        override fun onSensorChanged(event: SensorEvent?) {
            //X轴角速度 event.values?.get(0)!!
            // 将手机在各个轴上的旋转角度相加
            event?.run {
                //角速度乘以时间，就是转过的角度，直接计算旋转的角度值。
                angleX += (values[0] * dT).toLong()
                angleY += (values[1] * dT).toLong()
//                angularZ += (values[2] * dT).toLong()
                //设置x轴y轴最大边界值，
                if (angleY > mMaxAngle) {
                    angleY = mMaxAngle.toFloat()
                } else if (angleY < -mMaxAngle) {
                    angleY = -mMaxAngle.toFloat()
                }

                if (angleX > mMaxAngle) {
                    angleX = mMaxAngle.toFloat()
                } else if (angleX < -mMaxAngle) {
                    angleX = -mMaxAngle.toFloat()
                }
                //依据公式:旋转角度/最大角度 = 平移距离/最大平移距离,反推出 平移距离= 旋转角度/最大角度*最大平移距离
                val xRadio: Float = (angleY / mMaxAngle)
                val yRadio: Float = (angleX / mMaxAngle)
                x = abs(values[0])
                y = abs(values[1])
                z = abs(values[2])
//                Log.i(TAG, "onSensorChanged: $x,$y,$z")
                if (x > y + z) {
//                    xDistance = 0f
                    yDistance = yRadio * maxOffset
                } else if (y > x + z) {
                    xDistance = xRadio * maxOffset
//                    yDistance = 0f
                }

            }
        }

        override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
        }
    }, sensor, dT)

    Surface {
        Image(painter = painterResource(id = midImg),
            contentScale = contentScale,
            contentDescription = null,
            modifier = modifier
                .fillMaxWidth()
                .height(height)
                .scale(1.3f)
                .drawWithContent {
                    onDraw(xDistance, yDistance)
                })
    }
}

/***
 * @param mMaxAngle 最大角度
 * @param maxOffset 最大位移
 * @param backImg  图片Id
 * @param midImg  图片Id
 * @param foreImg  图片Id
 * @param isHeightProportion true为以高的比例缩放，false为以宽的比例缩放
 */
@Deprecated("仅做Canvas实现示例，实际实现方法一致")
@Composable
private fun Banner3D(
    @DrawableRes backImg: Int,
    @DrawableRes midImg: Int,
    @DrawableRes foreImg: Int,
    modifier: Modifier = Modifier,
    isHeightProportion: Boolean = true,
    mMaxAngle: Int = 30,
    maxOffset: Int = 30
) {
    val imageBack = ImageBitmap.imageResource(id = backImg)
    val imageMid = ImageBitmap.imageResource(id = midImg)
    val imageFore = ImageBitmap.imageResource(id = foreImg)
    var xDistance by remember { mutableStateOf(0f) }
    var yDistance by remember { mutableStateOf(0f) }
    val context = LocalContext.current
    val sensorManager: SensorManager? =
        ContextCompat.getSystemService(context, SensorManager::class.java)
    val sensor = sensorManager?.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
    //时间
    val dT = SENSOR_DELAY_GAME
    var angleX = 0f
    var angleY = 0f
//    var angularZ = 0f
    var x: Float
    var y: Float
    var z: Float
    sensorManager?.registerListener(object : SensorEventListener {
        override fun onSensorChanged(event: SensorEvent?) {
            //X轴角速度 event.values?.get(0)!!
            // 将手机在各个轴上的旋转角度相加
            event?.run {
                //角速度乘以时间，就是转过的角度，直接计算旋转的角度值。
                angleX += (values[0] * dT).toLong()
                angleY += (values[1] * dT).toLong()
//                angularZ += (values[2] * dT).toLong()
                //设置x轴y轴最大边界值，
                if (angleY > mMaxAngle) {
                    angleY = mMaxAngle.toFloat()
                } else if (angleY < -mMaxAngle) {
                    angleY = -mMaxAngle.toFloat()
                }

                if (angleX > mMaxAngle) {
                    angleX = mMaxAngle.toFloat()
                } else if (angleX < -mMaxAngle) {
                    angleX = -mMaxAngle.toFloat()
                }
                //依据公式:旋转角度/最大角度 = 平移距离/最大平移距离,反推出 平移距离= 旋转角度/最大角度*最大平移距离
                val xRadio: Float = (angleY / mMaxAngle)
                val yRadio: Float = (angleX / mMaxAngle)
                x = abs(values[0])
                y = abs(values[1])
                z = abs(values[2])
//                Log.i(TAG, "onSensorChanged: $x,$y,$z")
                if (x > y + z) {
//                    xDistance = 0f
                    yDistance = yRadio * maxOffset
                } else if (y > x + z) {
                    xDistance = xRadio * maxOffset
//                    yDistance = 0f
                }

            }
        }

        override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
        }
    }, sensor, dT)
    var isInit = false
    val midHeight = imageMid.height
    val midWidth = imageMid.width
    val foreHeight = imageFore.height
    val foreWidth = imageFore.width
    var w = 0
    var h = 0
    var midHeightProportion = 0
    var midWidthProportion = 0
    var foreHeightProportion = 0
    var foreWidthProportion = 0

    Surface {
        Canvas(
            modifier = modifier
                .fillMaxWidth()
                .height(200.dp)
                .scale(1.3f)
        ) {
            if (!isInit) {
                isInit = true
                h = size.height.toInt()
                w = size.width.toInt()
                Log.i(TAG, "Banner3D:init$h $w ")
                if (isHeightProportion) {
                    val d1 = midHeight.toDouble() / h
                    midHeightProportion = midHeight / d1.roundToInt()
                    midWidthProportion = midWidth / d1.roundToInt()
                    val d = foreHeight.toDouble() / h
                    foreHeightProportion = foreHeight / d.roundToInt()
                    foreWidthProportion = foreWidth / d.roundToInt()
                } else {
                    val d1 = midWidth.toDouble() / w
                    midHeightProportion = midHeight / d1.roundToInt()
                    midWidthProportion = midWidth / d1.roundToInt()
                    val d = foreWidth.toDouble() / w
                    foreHeightProportion = foreHeight / d.roundToInt()
                    foreWidthProportion = foreWidth / d.roundToInt()
                }
                Log.i(TAG, "Canvas:h:$h,w:$w ")
                Log.i(
                    TAG, "Mid:h:$midHeight,w:$midWidth h:$midHeightProportion,w:$midWidthProportion"
                )
                Log.i(
                    TAG,
                    "Fore:h:$foreHeight,w:$foreWidth h:$foreHeightProportion,w:$foreWidthProportion"
                )
            }

            translate(-xDistance, -yDistance, block = {
                drawImage(imageBack, dstSize = IntSize(w, h))
            })
            drawImage(
                imageMid, dstSize = IntSize(midWidthProportion, midHeightProportion)
            )
            translate(xDistance, yDistance, block = {
                drawImage(
                    imageFore,
                    dstSize = IntSize(foreWidthProportion, foreHeightProportion),
                )
            })
        }
    }
}


